package com.example.warehousewms.service.impl;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import com.example.warehousewms.bean.Inventory;
import com.example.warehousewms.bean.StockOutOrder;
import com.example.warehousewms.bean.StockOutOrderItem;
import com.example.warehousewms.bean.vo.StockOutOrderVo;
import com.example.warehousewms.mapper.InventoryMapper;
import com.example.warehousewms.mapper.StockOutOrderItemMapper;
import com.example.warehousewms.mapper.StockOutOrderMapper;
import com.example.warehousewms.service.StockOutOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class StockOutOrderServiceImpl implements StockOutOrderService {

    @Autowired
    StockOutOrderMapper stockOutOrderMapper;

    @Autowired
    StockOutOrderItemMapper stockOutOrderItemMapper;

    @Autowired
    InventoryMapper inventoryMapper;

    @Transactional
    @Override
    public void createStockOutOrder(StockOutOrderVo stockOutOrderVo) {

        StockOutOrder stockOutOrder = new StockOutOrder();
        // 生成出库单号
        stockOutOrder.setOrderNo("OON" + System.currentTimeMillis());
        stockOutOrder.setOrderType(stockOutOrderVo.getOrderType());
        stockOutOrder.setWarehouseId(stockOutOrderVo.getWarehouseId());
        stockOutOrder.setTotalQuantity(stockOutOrderVo.getTotalQuantity());
        stockOutOrder.setOrderStatus(stockOutOrderVo.getOrderStatus());
        stockOutOrder.setCreateTime(LocalDateTime.now());
        stockOutOrder.setUpdateTime(LocalDateTime.now());

        stockOutOrderMapper.insertStockOutOrder(stockOutOrder);

        Long stockOutOrderId = stockOutOrder.getId();

        List<StockOutOrderItem> list = new ArrayList<>();
        stockOutOrderVo.getStockOutOrderItemList().forEach(s -> {
            StockOutOrderItem stockOutOrderItem = new StockOutOrderItem();
            stockOutOrderItem.setStockOutOrderId(stockOutOrderId);
            stockOutOrderItem.setProductId(s.getProductId());
            stockOutOrderItem.setPlannedQuantity(s.getPlannedQuantity());
            stockOutOrderItem.setCreateTime(LocalDateTime.now());
            stockOutOrderItem.setUpdateTime(LocalDateTime.now());

            list.add(stockOutOrderItem);
        });

        stockOutOrderItemMapper.insertStockOutOrderItemList(list);


    }

    @Transactional
    @Override
    public void updateStockOutOrder(StockOutOrderVo stockOutOrderVo) {
        StockOutOrder stockOutOrder = new StockOutOrder();
        stockOutOrder.setId(stockOutOrderVo.getId());
        stockOutOrder.setOrderType(stockOutOrderVo.getOrderType());
        stockOutOrder.setWarehouseId(stockOutOrderVo.getWarehouseId());
        stockOutOrder.setCustomerInfo(stockOutOrderVo.getCustomerInfo());
        stockOutOrder.setTotalQuantity(stockOutOrderVo.getTotalQuantity());
        stockOutOrder.setActualTotalQuantity(stockOutOrderVo.getActualTotalQuantity());
        stockOutOrder.setOrderStatus(stockOutOrderVo.getOrderStatus());
        stockOutOrder.setLogisticsInfo(stockOutOrderVo.getLogisticsInfo());
        stockOutOrder.setUpdateTime(LocalDateTime.now());

        stockOutOrderMapper.updateStockOutOrder(stockOutOrder);

        if (stockOutOrderVo.getStockOutOrderItemList() != null && stockOutOrderVo.getStockOutOrderItemList().size() > 0){
            List<StockOutOrderItem> list = new ArrayList<>();

            stockOutOrderVo.getStockOutOrderItemList().forEach(s -> {
                StockOutOrderItem stockOutOrderItem = new StockOutOrderItem();
                stockOutOrderItem.setId(s.getId());
                stockOutOrderItem.setStockOutOrderId(s.getStockOutOrderId());
                stockOutOrderItem.setProductId(s.getProductId());
                stockOutOrderItem.setPlannedQuantity(s.getPlannedQuantity());
                stockOutOrderItem.setActualQuantity(s.getActualQuantity());
                stockOutOrderItem.setLocationId(s.getLocationId());
                stockOutOrderItem.setUpdateTime(LocalDateTime.now());
                list.add(stockOutOrderItem);
            });
            stockOutOrderItemMapper.updateStockOutOrderItemList(list);

        }

    }

    @Transactional
    @Override
    public void finishStockOutOrder(Long id) {
        StockOutOrder stockOutOrder = stockOutOrderMapper.getStockOutOrderById(id);
        if (stockOutOrder == null || !"APPROVED".equals(stockOutOrder.getOrderStatus())){
            throw new RuntimeException("该出库单状态无法完成");
        }

        // 检查库存是否充足
        List<StockOutOrderItem> items = stockOutOrderItemMapper.getStockOutItemByStockOutId(id);
        for (StockOutOrderItem s : items){
            Inventory inventory = inventoryMapper.getInventoryByProductIdAndLocationId(
                    s.getProductId(),
                    s.getLocationId());

            if (inventory == null || inventory.getQuantity() < s.getPlannedQuantity()){
                throw new RuntimeException("库存不足");
            }

            // 更新库存
            boolean b = checkAndReduceInventory(
                    s.getProductId(),
                    s.getLocationId(),
                    s.getActualQuantity(),
                    inventory.getVersion());
            if (!b){
                throw new RuntimeException("库存不足");
            }
        }
        stockOutOrder.setOrderStatus("COMPLETED");
        stockOutOrder.setUpdateTime(LocalDateTime.now());
        stockOutOrderMapper.updateStockOutOrder(stockOutOrder);

    }


    // 在扣减库存前，使用乐观锁再次检查
    public boolean checkAndReduceInventory(Long productId, Long locationId,
                                           Integer quantity, Integer version) {
        // 使用乐观锁，在UPDATE语句中同时检查版本号和库存数量
        int updatedRows = inventoryMapper.reduceQuantityWithLock(
                productId, locationId, quantity, version);

        return updatedRows > 0; // 如果>0表示更新成功，否则说明库存已被其他操作修改
    }


}
